# -*- coding: utf-8 -*-
"""camera.py
This code implements the Camera class, which encapsulates code to handle IP CAM, USB webcam.
"""
import logging
import threading
import platform
import numpy as np
import time
import cv2

is_linux = platform.system().lower() == 'linux'

def grab_img(cam):
    tic = time.time()
    """This 'grab_img' function is designed to be run in the sub-thread.
    Once started, this thread continues to grab a new image and put it
    into the global 'img_handle', until 'is_running' is set to False.
    """
    while cam.is_running:
        _, cam.img_handle = cam.cap.read()
        if cam.img_handle is None:
            logging.warning('Camera: cap.read() returns None...')
            break

        # calculate an exponentially decaying average of fps number
        toc = time.time()
        if toc == tic:
            continue
        fps = 1.0 / (toc - tic)
        cam.fps = (cam.fps*0.95 + fps*0.05)
        tic = toc

    cam.is_running = False

class Camera():
    """Camera class which supports reading images from RTSP (IP CAM) sources:
    """

    def __init__(self, rtsp):
        self.is_opened = False
        self.is_running = False
        self.img_handle = None
        self.copy_frame = False
        self.thread = None
        self.cap = None
        self.fps = 0.0
        self._open(rtsp)  # try to open the camera

    def _open(self, rtsp):
        """Open camera based on command line arguments."""
        if self.cap is not None:
            raise RuntimeError('camera is already opened!')
        self.cap = cv2.VideoCapture(rtsp)
        self._start()

    def isOpened(self):
        return self.is_opened

    def _start(self):
        if not self.cap.isOpened():
            logging.warning('Camera: starting while cap is not opened!')
            return

        # Try to grab the 1st image and determine width and height
        _, self.img_handle = self.cap.read()
        if self.img_handle is None:
            logging.warning('Camera: cap.read() returns no image!')
            self.is_opened = False
            return

        self.is_opened = True
        self.is_running = True
        self.thread = threading.Thread(target=grab_img, args=(self,))
        self.thread.start()

    def _stop(self):
        if self.is_running:
            self.is_running = False

    def read(self):
        """Read a frame from the camera object.
        Returns None if the camera runs out of image or error.
        """
        if not self.is_opened:
            return None

        if self.copy_frame:
            return self.img_handle.copy()
        return self.img_handle

    def release(self):
        self._stop()
        try:
            self.cap.release()
        except:
            pass

    def __del__(self):
        self.release()

if __name__ == '__main__':
    import sys

    #url = 'rtsp://192.168.144.119:554/H264?W=1280&H=720&BR=2000000&FPS=30'
    url = 'rtsp://192.168.144.119:554/live'
    cam = Camera(url)
    # cam.cap.set(cv2.CAP_PROP_FRAME_WIDTH, 2560)
    # cam.cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 1440)
    # cam.cap.set(cv2.CAP_PROP_FOURCC, cv2.VideoWriter.fourcc('M','J','p','G'))

    # w = int(cam.cap.get(cv2.CAP_PROP_FRAME_WIDTH))
    # h = int(cam.cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
    # fps = cam.cap.get(cv2.CAP_PROP_FPS)
    # print(f"实际分辨率: {w}×{h}  @{fps} fps")

    image_index = 1
    while True:
        img = cam.read()
        if img is None:
            print("No image received, exiting...")
            break
        print (f'{img.shape} FPS {cam.fps}')

        if is_linux:
            import select
            if select.select([sys.stdin], [], [], 0)[0]:
                key = sys.stdin.readline().strip()
                if key == 's': # 按S键抓拍照片
                    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

                    # Save image
                    status = cv2.imwrite(f'img-{image_index}.jpg', gray)
                    image_index = image_index + 1

                if key == 'q': # 按esc键退出
                    print('Quit ...')
                    break
        else:
            import msvcrt
            while msvcrt.kbhit():  # 如果有按键
                key = sys.stdin.readline().strip()
                if key == 's': # 按S键抓拍照片
                    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

                    # Save image
                    status = cv2.imwrite(f'img-{image_index}.jpg', gray)
                    image_index = image_index + 1

                if key == 'q': # 按esc键退出
                    print('Quit ...')
                    break
        # 显示结果框架
        if not is_linux:
            cv2.imshow("frame", img)
            if cv2.waitKey(1) & 0xFF == ord('q'):
                break

